package com.katze.boot.common.config.actuator.endpoint;

import org.springframework.boot.actuate.endpoint.OperationResponseBody;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.web.exchanges.HttpExchange;
import org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository;
import org.springframework.util.Assert;

import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Endpoint(id = "tracing")
public class HttpTraceEndpoint {

    private final HttpExchangeRepository repository;

    public HttpTraceEndpoint(HttpExchangeRepository repository) {
        Assert.notNull(repository, "Repository must not be null");
        this.repository = repository;
    }

    @ReadOperation
    public HttpTraceEndpoint.HttpExchangesDescriptor tracing() {
        return new HttpTraceEndpoint.HttpExchangesDescriptor(this.repository.findAll());
    }

    public static final class HttpExchangesDescriptor implements OperationResponseBody {
        private final List<HttpExchange> exchanges;

        private HttpExchangesDescriptor(List<HttpExchange> exchanges) {
            this.exchanges = exchanges;
        }

        public List<Map<String, Object>> getExchanges() {
            return this.exchanges.stream().map(item -> {
                Map<String, Object> data = new HashMap<>();
                data.put("timestamp", item.getTimestamp().atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")));
                data.put("request", item.getRequest());
                data.put("response", item.getResponse());
                data.put("timeTaken", item.getTimeTaken().toMillis());
                return data;
            }).collect(Collectors.toList());
        }
    }
}
